//Includes
#include <stdio.h>
#include <unistd.h>
#include <time.h>
#include "stdlib.h"
#include "sys/time.h"
#include <mpi.h>

#define SOURCE        	   0
#define RANDOM_MAX     	   1000
#define ARRAY_SIZE     	   10

int main(int argc, char *argv[])
{
	MPI_Init(&argc,&argv);

	int numtasks, rank, srandMax, srandMin;
	int array[ARRAY_SIZE] = {0};
	int min[ARRAY_SIZE] = {0};
	int max[ARRAY_SIZE] = {0};
	char msg[100] = {0};

	//MPI_Status status;

	MPI_Comm_size(MPI_COMM_WORLD, &numtasks);
	MPI_Comm_rank(MPI_COMM_WORLD, &rank);

	srand (time(0) + rank);

	if(rank == SOURCE)
	{
		// root process create a random max/min for the number generation(rand)
		srandMin = rand() % RANDOM_MAX;
		srandMax = rand() % RANDOM_MAX;
		printf("Each process will fill and array of size %d with numbers randomly generated between: %d and %d\n",ARRAY_SIZE, srandMin, srandMax); fflush(stdout);
	}

	// we broadcast the max/min to the other process
	MPI_Bcast(&srandMin, 1, MPI_INT, SOURCE, MPI_COMM_WORLD);
	MPI_Bcast(&srandMax, 1, MPI_INT, SOURCE, MPI_COMM_WORLD);

	// each process fill the array with random numbers between srandMin and srandMax
	int i;
	for(i = 0; i < ARRAY_SIZE; i++){
		array[i] = (rand() % (srandMax-srandMin) + srandMin);
	}

	// each process print the content of its array
	sprintf(msg, "Array in process #%d contain: ", rank); fflush(stdout);
	for(i = 0; i < ARRAY_SIZE; i++){
		sprintf(msg, "%s %d", msg, array[i]); fflush(stdout);
	}
	sprintf(msg, "%s \n",msg); fflush(stdout);
	printf("%s",msg);

	// we sync process
	MPI_Barrier(MPI_COMM_WORLD);

	MPI_Reduce(array, min, ARRAY_SIZE, MPI_INT, MPI_MIN, SOURCE, MPI_COMM_WORLD);
	MPI_Reduce(array, max, ARRAY_SIZE, MPI_INT, MPI_MAX, SOURCE, MPI_COMM_WORLD);

	// we print min/max for each index
	if(rank == SOURCE)
	{
		for(i = 0; i < ARRAY_SIZE; i++){
			sprintf(msg, "Minimum value contain at the index %d among all the arrays is %d and maximum value is %d\n", i, min[i], max[i]); fflush(stdout);
			printf("%s",msg);
		}
	}

	MPI_Finalize();
	return 0;
}
